/****************************************************************
 * Fulguro
 * Copyright (C) 2004 Christophe Clienti
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 ***************************************************************/

#include <string.h>
#include <flgrCoreVector.h>
#include <flgrCoreDispatch.h>
#include <flgrCoreArithDef.h>
#include <flgrCoreIO.h>
#include "flgrArithShiftFast.h"

#ifdef __SSE3__
#include <pmmintrin.h>
#endif

#ifdef __SSE2__
#include <emmintrin.h>
#include <xmmintrin.h>
#endif

#if defined(__SSE__)
#include <xmmintrin.h>
#endif

#if defined(__MMX__)
#include <mmintrin.h>
#endif


#ifdef __SSE3__
#define vector128_load_unalign(x) _mm_lddqu_si128(x)
#else
#ifdef __SSE2__
#define vector128_load_unalign(x) _mm_loadu_si128(x)
#endif
#endif






//////////////////////////////////////////////////////////////////////////
// FLGR_BIT MACRO
//////////////////////////////////////////////////////////////////////////

#define tbit fgBIT
#define set(x)  ((fgBIT) (x));
#define shiftr(a,x) ((a)>>(x))
#define shiftl(a,x) ((a)<<(x))
#define and(a,b) ((a) & (b))
#define or(a,b) ((a) | (b))
#define empty() 

#define FLGR_MACRO_1D_ARITH_OP_SHIFT_RIGHT_BIT(op,border)	\
  tbit *pdest = (tbit*) datdest->array;				\
  tbit *psrc = (tbit*) data1->array;				\
  tbit r0;							\
  tbit r1;							\
  tbit r2;							\
  tbit rmask;							\
  int i;							\
  int nbvec = datdest->length / (sizeof(tbit)*8);		\
								\
  r2 = set( ((fgBIT) border)<<(sizeof(tbit)*8-1) );		\
  rmask = set(1);						\
								\
  for(i=0 ; i<=nbvec; i++, psrc++, pdest++) {			\
    r0 = *psrc;							\
    r1 = shiftr(r0,1);						\
    r1 = or(r2,r1);						\
    r1 = op(r1,r0);						\
    r2 = and(r0,rmask);						\
    r2 = shiftl(r2,(sizeof(tbit)*8-1));				\
    *pdest = r1;						\
  }								\
  empty()


#define FLGR_MACRO_1D_ARITH_OP_SHIFT_LEFT_BIT(op,border)	\
  tbit *pdest = (tbit*) datdest->array;				\
  tbit *psrc = (tbit*) data1->array;				\
  tbit r0;							\
  tbit r1;							\
  tbit r2;							\
  tbit rmask;							\
  int i;							\
  int nbvec = datdest->length / (sizeof(tbit)*8);		\
  int posvec = (sizeof(tbit)*8)-				\
    (datdest->length % (sizeof(tbit)*8));			\
  								\
  rmask = set(((fgBIT) 1)<<(sizeof(tbit)*8-1));			\
								\
  r2 = set( ((fgBIT) border)<<posvec );				\
								\
  psrc += nbvec;						\
  pdest += nbvec;						\
								\
  for(i=0 ; i<=nbvec ; i++, psrc--, pdest--) {			\
    r0 = *psrc;							\
    r1 = shiftl(r0,1);						\
    r1 = or(r2,r1);						\
    r1 = op(r1,r0);						\
    r2 = and(r0,rmask);						\
    r2 = shiftr(r2,(sizeof(tbit)*8-1));				\
    *pdest = r1;						\
  }								\
  empty()



//////////////////////////////////////////////////////////////////////////
// MMX / SSE MACRO
//////////////////////////////////////////////////////////////////////////
#define FLGR_MACRO_1D_ARITH_OP_SHIFT_RIGHT_SSE(dtype,vtype,		\
					       scalar_instr,		\
					       vector_instr)		\
  const int spp = datdest->spp;						\
  const int sfsize = spp*right_shift_size;				\
  const int length = datdest->length*spp;				\
  const int vec_length = sizeof(vtype)/sizeof(dtype);			\
  dtype *psrc1 = (dtype*) data1->array;					\
  dtype *pdest = (dtype*) datdest->array;				\
  dtype result;								\
  vtype *vec_src1;							\
  vtype *vec_src2;							\
  vtype *vec_dest;							\
  vtype vec1;								\
  vtype vec2;								\
  int j;								\
									\
  FLGR_DECLARE_FUNCTION;						\
  									\
  for(j=0 ; j<sfsize ; j++) {						\
    result = flgr_get_array_##dtype(psrc1,j);				\
    flgr_set_array_##dtype(pdest,j,result);				\
  }									\
									\
  vec_src1 = (vtype*) (psrc1+sfsize);					\
  vec_src2 = (vtype*) psrc1;						\
  vec_dest = (vtype*) (pdest+sfsize);					\
									\
  for(j=sfsize ; j<length ; j+=vec_length) {				\
    vec1 = *vec_src1;							\
    vec2 = *vec_src2;							\
    vec1 = vector_instr(vec1,vec2);					\
    *vec_dest = vec1;							\
    vec_dest++;vec_src2++;vec_src1++;					\
  }									\
									\
  _mm_empty();								\
  return



#define FLGR_MACRO_1D_ARITH_OP_SHIFT_LEFT_SSE(dtype,vtype,		\
					      scalar_instr,		\
					      vector_instr)		\
  const int spp = datdest->spp;						\
  const int sfsize = spp*left_shift_size;				\
  const int length = datdest->length*spp;				\
  const int vec_length = sizeof(vtype)/sizeof(dtype);			\
  dtype *psrc1 = (dtype*) data1->array;					\
  dtype *pdest = (dtype*) datdest->array;				\
  dtype result;								\
  vtype *vec_src1;							\
  vtype *vec_src2;							\
  vtype *vec_dest;							\
  vtype vec1;								\
  vtype vec2;								\
  int j;								\
									\
  FLGR_DECLARE_FUNCTION;						\
  									\
  vec_src1 = (vtype*) psrc1;						\
  vec_src2 = (vtype*) (psrc1+sfsize);					\
  vec_dest = (vtype*) pdest;						\
									\
  for(j=0 ; j<length-sfsize ; j+=vec_length) {				\
    vec1 = *vec_src1;							\
    vec2 = *vec_src2;							\
    vec1 = vector_instr(vec1,vec2);					\
    *vec_dest = vec1;							\
    vec_dest++;vec_src2++;vec_src1++;					\
  }									\
									\
  for(j=length-sfsize ; j<length ; j++) {				\
    result = flgr_get_array_##dtype(psrc1,j);				\
    flgr_set_array_##dtype(pdest,j,result);				\
  }									\
									\
  _mm_empty();								\
  return




#define FLGR_MACRO_1D_ARITH_OP_SHIFT_RIGHT_SSE_FLOAT32(scalar_instr,	\
						       vector_instr)	\
  const int spp = datdest->spp;						\
  const int sfsize = spp*right_shift_size;				\
  const int length = datdest->length*spp;				\
  const int vec_length = sizeof(__m128)/sizeof(fgFLOAT32);		\
  fgFLOAT32 *psrc1 = (fgFLOAT32*) data1->array;				\
  fgFLOAT32 *pdest = (fgFLOAT32*) datdest->array;			\
  fgFLOAT32 result;							\
  __m128 *vec_src1;							\
  __m128 *vec_src2;							\
  __m128 *vec_dest;							\
  __m128 vec1;								\
  __m128 vec2;								\
  int j;								\
									\
  FLGR_DECLARE_FUNCTION;						\
  									\
  for(j=0 ; j<sfsize ; j++) {						\
    result = flgr_get_array_fgFLOAT32(psrc1,j);				\
    flgr_set_array_fgFLOAT32(pdest,j,result);				\
  }									\
									\
  vec_src1 = (__m128*) (psrc1+sfsize);					\
  vec_src2 = (__m128*) psrc1;						\
  vec_dest = (__m128*) (pdest+sfsize);					\
									\
  for(j=sfsize ; j<length ; j+=vec_length) {				\
    vec1 = _mm_loadu_ps((float*) vec_src1);				\
    vec2 = _mm_loadu_ps((float*) vec_src2);				\
    vec1 = vector_instr(vec1,vec2);					\
    _mm_storeu_ps((float*) vec_dest,vec1);				\
    vec_dest++;vec_src2++;vec_src1++;					\
  }									\
									\
  return

#define FLGR_MACRO_1D_ARITH_OP_SHIFT_LEFT_SSE_FLOAT32(scalar_instr,	\
						      vector_instr)	\
  const int spp = datdest->spp;						\
  const int sfsize = spp*left_shift_size;				\
  const int length = datdest->length*spp;				\
  const int vec_length = sizeof(__m128)/sizeof(fgFLOAT32);		\
  fgFLOAT32 *psrc1 = (fgFLOAT32*) data1->array;				\
  fgFLOAT32 *pdest = (fgFLOAT32*) datdest->array;			\
  fgFLOAT32 result;							\
  __m128 *vec_src1;							\
  __m128 *vec_src2;							\
  __m128 *vec_dest;							\
  __m128 vec1;								\
  __m128 vec2;								\
  int j;								\
									\
  FLGR_DECLARE_FUNCTION;						\
  									\
  vec_src1 = (__m128*) psrc1;						\
  vec_src2 = (__m128*) (psrc1+sfsize);					\
  vec_dest = (__m128*) pdest;						\
									\
  for(j=0 ; j<length-sfsize ; j+=vec_length) {				\
    vec1 = _mm_loadu_ps((float*) vec_src1);				\
    vec2 = _mm_loadu_ps((float*) vec_src2);				\
    vec1 = vector_instr(vec1,vec2);					\
    _mm_storeu_ps((float*) vec_dest,vec1);				\
    vec_dest++;vec_src2++;vec_src1++;					\
  }									\
									\
  for(j=length-sfsize ; j<length ; j++) {				\
    result = flgr_get_array_fgFLOAT32(psrc1,j);				\
    flgr_set_array_fgFLOAT32(pdest,j,result);				\
  }									\
									\
  return



//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// SSE2 MACRO
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////



#define FLGR_MACRO_1D_ARITH_OP_SHIFT_RIGHT_SSE2(dtype,vtype,		\
						scalar_instr,		\
						vector_instr)		\
  const int spp = datdest->spp;						\
  const int sfsize = spp*right_shift_size;				\
  const int length = datdest->length*spp;				\
  const int vec_length = sizeof(vtype)/sizeof(dtype);			\
  dtype *psrc1 = (dtype*) data1->array;					\
  dtype *pdest = (dtype*) datdest->array;				\
  dtype result;								\
  vtype *vec_src1;							\
  vtype *vec_src2;							\
  vtype *vec_dest;							\
  vtype vec1;								\
  vtype vec2;								\
  int j;								\
									\
  FLGR_DECLARE_FUNCTION;						\
  									\
  for(j=0 ; j<sfsize ; j++) {						\
    result = flgr_get_array_##dtype(psrc1,j);				\
    flgr_set_array_##dtype(pdest,j,result);				\
  }									\
									\
  vec_src1 = (vtype*) (psrc1+sfsize);					\
  vec_src2 = (vtype*) psrc1;						\
  vec_dest = (vtype*) (pdest+sfsize);					\
									\
  for(j=sfsize ; j<length ; j+=vec_length) {				\
    vec1 = vector128_load_unalign(vec_src1);				\
    vec2 = _mm_load_si128(vec_src2);					\
    vec1 = vector_instr(vec1,vec2);					\
    _mm_storeu_si128(vec_dest,vec1);					\
    vec_dest++;vec_src2++;vec_src1++;					\
  }									\
									\
  return


#define FLGR_MACRO_1D_ARITH_OP_SHIFT_LEFT_SSE2(dtype,vtype,		\
					       scalar_instr,		\
					       vector_instr)		\
  const int spp = datdest->spp;						\
  const int sfsize = spp*left_shift_size;				\
  const int length = datdest->length*spp;				\
  const int vec_length = sizeof(vtype)/sizeof(dtype);			\
  dtype *psrc1 = (dtype*) data1->array;					\
  dtype *pdest = (dtype*) datdest->array;				\
  dtype result;								\
  vtype *vec_src1;							\
  vtype *vec_src2;							\
  vtype *vec_dest;							\
  vtype vec1;								\
  vtype vec2;								\
  int j;								\
									\
  FLGR_DECLARE_FUNCTION;						\
  									\
  vec_src1 = (vtype*) psrc1;						\
  vec_src2 = (vtype*) (psrc1+sfsize);					\
  vec_dest = (vtype*) pdest;						\
									\
  for(j=0 ; j<length-sfsize ; j+=vec_length) {				\
    vec1 = _mm_load_si128(vec_src1);					\
    vec2 = vector128_load_unalign(vec_src2);				\
    vec1 = vector_instr(vec1,vec2);					\
    _mm_store_si128(vec_dest,vec1);					\
    vec_dest++;vec_src2++;vec_src1++;					\
  }									\
									\
  for(j=length-sfsize ; j<length ; j++) {				\
    result = flgr_get_array_##dtype(psrc1,j);				\
    flgr_set_array_##dtype(pdest,j,result);				\
  }									\
									\
  return



#define FLGR_MACRO_1D_ARITH_OP_SHIFT_1_RIGHT_SSE2(dtype,vtype,		\
						  scalar_instr,		\
						  vector_instr)		\
  const int spp = datdest->spp;						\
  const int length = datdest->length*spp;				\
  const int vec_length = sizeof(vtype)/sizeof(dtype);			\
  dtype *psrc = (dtype*) data1->array;					\
  dtype *pdest = (dtype*) datdest->array;				\
  dtype sca1;								\
  dtype sca2;								\
  vtype *vec_src;							\
  vtype *vec_dest;							\
  vtype vec1;								\
  vtype vec2;								\
  int j;								\
									\
  FLGR_DECLARE_FUNCTION;						\
  									\
  vec_src = (vtype*) (psrc);						\
  vec_dest = (vtype*) (pdest);						\
									\
  vec1 = _mm_load_si128(vec_src);					\
  vec2 = _mm_slli_si128(vec1,1);					\
  vec1 = vector_instr(vec1,vec2);					\
  _mm_store_si128(vec_dest,vec1);					\
									\
  sca1 = flgr_get_array_##dtype(psrc,0);				\
  flgr_set_array_##dtype(pdest,0,sca1);					\
  									\
  vec_src++;vec_dest++;							\
									\
  									\
  for(j=vec_length ; j<length ; j+=vec_length,vec_src++,vec_dest++) {	\
    vec1 = _mm_load_si128(vec_src);					\
    vec2 = _mm_slli_si128(vec1,1);					\
    vec1 = vector_instr(vec1,vec2);					\
    _mm_store_si128(vec_dest,vec1);					\
									\
    sca1 = flgr_get_array_##dtype(psrc,j-1);				\
    sca2 = flgr_get_array_##dtype(psrc,j);				\
    sca1 = scalar_instr(sca1,sca2);					\
    flgr_set_array_##dtype(pdest,j,sca1);				\
  }									\
									\
  return



#define FLGR_MACRO_1D_ARITH_OP_SHIFT_1_LEFT_SSE2(dtype,vtype,		\
						  scalar_instr,		\
						  vector_instr)		\
  const int spp = datdest->spp;						\
  const int length = datdest->length*spp;				\
  const int vec_length = sizeof(vtype)/sizeof(dtype);			\
  dtype *psrc = (dtype*) data1->array;					\
  dtype *pdest = (dtype*) datdest->array;				\
  dtype sca1;								\
  dtype sca2;								\
  vtype *vec_src;							\
  vtype *vec_dest;							\
  vtype vec1;								\
  vtype vec2;								\
  int j;								\
									\
  FLGR_DECLARE_FUNCTION;						\
  									\
  vec_src = (vtype*) (psrc);						\
  vec_dest = (vtype*) (pdest);						\
									\
  for(j=0 ; j<length-vec_length ; j+=vec_length,vec_src++,vec_dest++) { \
    vec1 = _mm_load_si128(vec_src);					\
    vec2 = _mm_srli_si128(vec1,1);					\
    vec1 = vector_instr(vec1,vec2);					\
    _mm_store_si128(vec_dest,vec1);					\
									\
    sca1 = flgr_get_array_##dtype(psrc,j+vec_length-1);			\
    sca2 = flgr_get_array_##dtype(psrc,j+vec_length);			\
    sca1 = scalar_instr(sca1,sca2);					\
    flgr_set_array_##dtype(pdest,j+vec_length-1,sca1);			\
  }									\
									\
  j=length-vec_length;							\
									\
  vec1 = _mm_load_si128(vec_src);					\
  vec2 = _mm_srli_si128(vec1,1);					\
  vec1 = vector_instr(vec1,vec2);					\
  _mm_store_si128(vec_dest,vec1);					\
  sca1 = flgr_get_array_##dtype(psrc,j+vec_length-1);			\
  flgr_set_array_##dtype(pdest,j+vec_length-1,sca1);			\
   									\
  return






#define FLGR_MACRO_1D_ARITH_OP_SHIFT_RIGHT_SSE2_FLOAT64(scalar_instr,	\
							vector_instr)	\
  const int spp = datdest->spp;						\
  const int sfsize = spp*right_shift_size;				\
  const int length = datdest->length*spp;				\
  const int vec_length = sizeof(__m128d)/sizeof(fgFLOAT64);		\
  fgFLOAT64 *psrc1 = (fgFLOAT64*) data1->array;				\
  fgFLOAT64 *pdest = (fgFLOAT64*) datdest->array;			\
  fgFLOAT64 result;							\
  __m128d *vec_src1;							\
  __m128d *vec_src2;							\
  __m128d *vec_dest;							\
  __m128d vec1;								\
  __m128d vec2;								\
  int j;								\
									\
  FLGR_DECLARE_FUNCTION;						\
  									\
  for(j=0 ; j<sfsize ; j++) {						\
    result = flgr_get_array_fgFLOAT64(psrc1,j);				\
    flgr_set_array_fgFLOAT64(pdest,j,result);				\
  }									\
									\
  vec_src1 = (__m128d*) (psrc1+sfsize);					\
  vec_src2 = (__m128d*) psrc1;						\
  vec_dest = (__m128d*) (pdest+sfsize);					\
									\
  for(j=sfsize ; j<length ; j+=vec_length) {				\
    vec1 = _mm_loadu_pd((double*) vec_src1);				\
    vec2 = _mm_loadu_pd((double*) vec_src2);				\
    vec1 = vector_instr(vec1,vec2);					\
    _mm_storeu_pd((double*) vec_dest,vec1);				\
    vec_dest++;vec_src2++;vec_src1++;					\
  }									\
									\
  return


#define FLGR_MACRO_1D_ARITH_OP_SHIFT_LEFT_SSE2_FLOAT64(scalar_instr,	\
						       vector_instr)	\
  const int spp = datdest->spp;						\
  const int sfsize = spp*left_shift_size;				\
  const int length = datdest->length*spp;				\
  const int vec_length = sizeof(__m128d)/sizeof(fgFLOAT64);		\
  fgFLOAT64 *psrc1 = (fgFLOAT64*) data1->array;				\
  fgFLOAT64 *pdest = (fgFLOAT64*) datdest->array;			\
  fgFLOAT64 result;							\
  __m128d *vec_src1;							\
  __m128d *vec_src2;							\
  __m128d *vec_dest;							\
  __m128d vec1;								\
  __m128d vec2;								\
  int j;								\
									\
  FLGR_DECLARE_FUNCTION;						\
  									\
  vec_src1 = (__m128d*) psrc1;						\
  vec_src2 = (__m128d*) (psrc1+sfsize);					\
  vec_dest = (__m128d*) pdest;						\
									\
  for(j=0 ; j<length-sfsize ; j+=vec_length) {				\
    vec1 = _mm_loadu_pd((double*) vec_src1);				\
    vec2 = _mm_loadu_pd((double*) vec_src2);				\
    vec1 = vector_instr(vec1,vec2);					\
    _mm_storeu_pd((double*) vec_dest,vec1);				\
    vec_dest++;vec_src2++;vec_src1++;					\
  }									\
									\
  for(j=length-sfsize ; j<length ; j++) {				\
    result = flgr_get_array_fgFLOAT64(psrc1,j);				\
    flgr_set_array_fgFLOAT64(pdest,j,result);				\
  }									\
									\
  return







void flgr1d_arith_sup_shift_1_right_fast_fgBIT(FLGR_Data1D *datdest, FLGR_Data1D *data1) {
  FLGR_MACRO_1D_ARITH_OP_SHIFT_RIGHT_BIT(or,0);
}
void flgr1d_arith_sup_shift_right_fast_fgUINT8(FLGR_Data1D *datdest, FLGR_Data1D *data1, int right_shift_size) {
#ifdef __SSE2__
  if((right_shift_size==1)&&(datdest->spp==1)) {
    FLGR_MACRO_1D_ARITH_OP_SHIFT_1_RIGHT_SSE2(fgUINT8, __m128i, flgr_defop_sup_fgUINT8, _mm_max_epu8);
  }else{
    FLGR_MACRO_1D_ARITH_OP_SHIFT_RIGHT_SSE2(fgUINT8, __m128i, flgr_defop_sup_fgUINT8, _mm_max_epu8);
  }
#else
#if defined(__MMX__) && defined(__SSE__)
  FLGR_MACRO_1D_ARITH_OP_SHIFT_RIGHT_SSE(fgUINT8, __m64, flgr_defop_sup_fgUINT8, _mm_max_pu8);
#else
  POST_ERROR("SSE or SSE2 not activated\n");
#endif
#endif
}
void flgr1d_arith_sup_shift_right_fast_fgINT16(FLGR_Data1D *datdest, FLGR_Data1D *data1, int right_shift_size) {
#ifdef __SSE2__
  FLGR_MACRO_1D_ARITH_OP_SHIFT_RIGHT_SSE2(fgINT16, __m128i, flgr_defop_sup_fgINT16, _mm_max_epi16);
#else
#if defined(__MMX__) && defined(__SSE__)
  FLGR_MACRO_1D_ARITH_OP_SHIFT_RIGHT_SSE(fgINT16, __m64, flgr_defop_sup_fgINT16, _mm_max_pi16);
#else
  POST_ERROR("SSE or SSE2 not activated\n");
#endif
#endif
}
void flgr1d_arith_sup_shift_right_fast_fgFLOAT32(FLGR_Data1D *datdest, FLGR_Data1D *data1, int right_shift_size) {
#if defined(__MMX__) && defined(__SSE__)
  FLGR_MACRO_1D_ARITH_OP_SHIFT_RIGHT_SSE_FLOAT32(flgr_defop_sup_fgFLOAT32, _mm_max_ps);
#else
  POST_ERROR("SSE or SSE2 not activated\n");
#endif
}
void flgr1d_arith_sup_shift_right_fast_fgFLOAT64(FLGR_Data1D *datdest, FLGR_Data1D *data1, int right_shift_size) {
#ifdef __SSE2__
  FLGR_MACRO_1D_ARITH_OP_SHIFT_RIGHT_SSE2_FLOAT64(flgr_defop_sup_fgFLOAT64, _mm_max_pd);
#else
  POST_ERROR("SSE or SSE2 not activated\n");
#endif
}














void flgr1d_arith_sup_shift_1_left_fast_fgBIT(FLGR_Data1D *datdest, FLGR_Data1D *data1) {
  FLGR_MACRO_1D_ARITH_OP_SHIFT_LEFT_BIT(or,0);
}
void flgr1d_arith_sup_shift_left_fast_fgUINT8(FLGR_Data1D *datdest, FLGR_Data1D *data1, int left_shift_size) {
#ifdef __SSE2__
/*   if((left_shift_size==1)&&(datdest->spp==1)) { */
/*     FLGR_MACRO_1D_ARITH_OP_SHIFT_1_LEFT_SSE2(fgUINT8, __m128i, flgr_defop_sup_fgUINT8, _mm_max_epu8); */
/*   }else{ */
    FLGR_MACRO_1D_ARITH_OP_SHIFT_LEFT_SSE2(fgUINT8, __m128i, flgr_defop_sup_fgUINT8, _mm_max_epu8);
/*   } */
#else
#if defined(__MMX__) && defined(__SSE__)
  FLGR_MACRO_1D_ARITH_OP_SHIFT_LEFT_SSE(fgUINT8, __m64, flgr_defop_sup_fgUINT8, _mm_max_pu8);
#else
  POST_ERROR("SSE or SSE2 not activated\n");
#endif
#endif
}
void flgr1d_arith_sup_shift_left_fast_fgINT16(FLGR_Data1D *datdest, FLGR_Data1D *data1, int left_shift_size) {
#ifdef __SSE2__
  FLGR_MACRO_1D_ARITH_OP_SHIFT_LEFT_SSE2(fgINT16, __m128i, flgr_defop_sup_fgINT16, _mm_max_epi16);
#else
#if defined(__MMX__) && defined(__SSE__)
  FLGR_MACRO_1D_ARITH_OP_SHIFT_LEFT_SSE(fgINT16, __m64, flgr_defop_sup_fgINT16, _mm_max_pi16);
#else
  POST_ERROR("SSE or SSE2 not activated\n");
#endif
#endif
}
void flgr1d_arith_sup_shift_left_fast_fgFLOAT32(FLGR_Data1D *datdest, FLGR_Data1D *data1, int left_shift_size) {
#if defined(__MMX__) && defined(__SSE__)
  FLGR_MACRO_1D_ARITH_OP_SHIFT_LEFT_SSE_FLOAT32(flgr_defop_sup_fgFLOAT32, _mm_max_ps);
#else
  POST_ERROR("SSE or SSE2 not activated\n");
#endif
}
void flgr1d_arith_sup_shift_left_fast_fgFLOAT64(FLGR_Data1D *datdest, FLGR_Data1D *data1, int left_shift_size) {
#ifdef __SSE2__
  FLGR_MACRO_1D_ARITH_OP_SHIFT_LEFT_SSE2_FLOAT64(flgr_defop_sup_fgFLOAT64, _mm_max_pd);
#else
  POST_ERROR("SSE or SSE2 not activated\n");
#endif
}










void flgr1d_arith_inf_shift_1_right_fast_fgBIT(FLGR_Data1D *datdest, FLGR_Data1D *data1) {
  FLGR_MACRO_1D_ARITH_OP_SHIFT_RIGHT_BIT(and,1);
}
void flgr1d_arith_inf_shift_right_fast_fgUINT8(FLGR_Data1D *datdest, FLGR_Data1D *data1, int right_shift_size) {
#ifdef __SSE2__
  if((right_shift_size==1)&&(datdest->spp==1)) {
    FLGR_MACRO_1D_ARITH_OP_SHIFT_1_RIGHT_SSE2(fgUINT8, __m128i, flgr_defop_inf_fgUINT8, _mm_min_epu8);
  }else{
    FLGR_MACRO_1D_ARITH_OP_SHIFT_RIGHT_SSE2(fgUINT8, __m128i, flgr_defop_inf_fgUINT8, _mm_min_epu8);
  }
#else
#if defined(__MMX__) && defined(__SSE__)
  FLGR_MACRO_1D_ARITH_OP_SHIFT_RIGHT_SSE(fgUINT8, __m64, flgr_defop_inf_fgUINT8, _mm_min_pu8);
#else
  POST_ERROR("SSE or SSE2 not activated\n");
#endif
#endif
}
void flgr1d_arith_inf_shift_right_fast_fgINT16(FLGR_Data1D *datdest, FLGR_Data1D *data1, int right_shift_size) {
#ifdef __SSE2__
  FLGR_MACRO_1D_ARITH_OP_SHIFT_RIGHT_SSE2(fgINT16, __m128i, flgr_defop_inf_fgINT16, _mm_min_epi16);
#else
#if defined(__MMX__) && defined(__SSE__)
  FLGR_MACRO_1D_ARITH_OP_SHIFT_RIGHT_SSE(fgINT16, __m64, flgr_defop_inf_fgINT16, _mm_min_pi16);
#else
  POST_ERROR("SSE or SSE2 not activated\n");
#endif
#endif
}
void flgr1d_arith_inf_shift_right_fast_fgFLOAT32(FLGR_Data1D *datdest, FLGR_Data1D *data1, int right_shift_size) {
#if defined(__MMX__) && defined(__SSE__)
  FLGR_MACRO_1D_ARITH_OP_SHIFT_RIGHT_SSE_FLOAT32(flgr_defop_inf_fgFLOAT32, _mm_min_ps);
#else
  POST_ERROR("SSE or SSE2 not activated\n");
#endif
}
void flgr1d_arith_inf_shift_right_fast_fgFLOAT64(FLGR_Data1D *datdest, FLGR_Data1D *data1, int right_shift_size) {
#ifdef __SSE2__
  FLGR_MACRO_1D_ARITH_OP_SHIFT_RIGHT_SSE2_FLOAT64(flgr_defop_inf_fgFLOAT64, _mm_min_pd);
#else
  POST_ERROR("SSE or SSE2 not activated\n");
#endif
}
















void flgr1d_arith_inf_shift_1_left_fast_fgBIT(FLGR_Data1D *datdest, FLGR_Data1D *data1) {
  FLGR_MACRO_1D_ARITH_OP_SHIFT_LEFT_BIT(and,1);
}
void flgr1d_arith_inf_shift_left_fast_fgUINT8(FLGR_Data1D *datdest, FLGR_Data1D *data1, int left_shift_size) {
#ifdef __SSE2__
/*   if((left_shift_size==1)&&(datdest->spp==1)) { */
/*     FLGR_MACRO_1D_ARITH_OP_SHIFT_1_LEFT_SSE2(fgUINT8, __m128i, flgr_defop_inf_fgUINT8, _mm_min_epu8); */
/*   }else{ */
    FLGR_MACRO_1D_ARITH_OP_SHIFT_LEFT_SSE2(fgUINT8, __m128i, flgr_defop_inf_fgUINT8, _mm_min_epu8);
/*   } */
#else
#if defined(__MMX__) && defined(__SSE__)
  FLGR_MACRO_1D_ARITH_OP_SHIFT_LEFT_SSE(fgUINT8, __m64, flgr_defop_inf_fgUINT8, _mm_min_pu8);
#else
  POST_ERROR("SSE or SSE2 not activated\n");
#endif
#endif
}
void flgr1d_arith_inf_shift_left_fast_fgINT16(FLGR_Data1D *datdest, FLGR_Data1D *data1, int left_shift_size) {
#ifdef __SSE2__
  FLGR_MACRO_1D_ARITH_OP_SHIFT_LEFT_SSE2(fgINT16, __m128i, flgr_defop_inf_fgINT16, _mm_min_epi16);
#else
#if defined(__MMX__) && defined(__SSE__)
  FLGR_MACRO_1D_ARITH_OP_SHIFT_LEFT_SSE(fgINT16, __m64, flgr_defop_inf_fgINT16, _mm_min_pi16);
#else
  POST_ERROR("SSE or SSE2 not activated\n");
#endif
#endif
}
void flgr1d_arith_inf_shift_left_fast_fgFLOAT32(FLGR_Data1D *datdest, FLGR_Data1D *data1, int left_shift_size) {
#if defined(__MMX__) && defined(__SSE__)
  FLGR_MACRO_1D_ARITH_OP_SHIFT_LEFT_SSE_FLOAT32(flgr_defop_inf_fgFLOAT32, _mm_min_ps);
#else
  POST_ERROR("SSE or SSE2 not activated\n");
#endif
}
void flgr1d_arith_inf_shift_left_fast_fgFLOAT64(FLGR_Data1D *datdest, FLGR_Data1D *data1, int left_shift_size) {
#ifdef __SSE2__
  FLGR_MACRO_1D_ARITH_OP_SHIFT_LEFT_SSE2_FLOAT64(flgr_defop_inf_fgFLOAT64, _mm_min_pd);
#else
  POST_ERROR("SSE or SSE2 not activated\n");
#endif
}






